package com.yunqian.util.swiftpass;

import com.alibaba.fastjson.JSON;
import com.yunqian.constant.RedDotKey;
import com.yunqian.constant.SwiftpassConfig;
import com.yunqian.exception.ServiceException;
import com.yunqian.util.HttpUtil;
import com.yunqian.util.RandomUtil;
import lombok.extern.log4j.Log4j2;
import org.dom4j.DocumentException;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author czy
 * @describe
 * @date 2018/10/16
 */
@Log4j2
public class SwiftpassUtil {

    /**
     * 查询订单API
     * https://open.swiftpass.cn/openapi/doc?index_1=3&index_2=1&chapter_1=191&chapter_2=216
     */
    public static Map<String, String> query(String outTradeNo) {

        // 接口类型
        String service = "unified.trade.query";
        // 商户号
        String mchId = SwiftpassConfig.MCH_ID;
        // 随机字符串
        String nonceStr = getNonceStr();
        // 签名
        String sign;

        Map<String, String> tempMap = new HashMap<>(16);
        tempMap.put("service", service);
        tempMap.put("mch_id", mchId);
        tempMap.put("out_trade_no", outTradeNo);
        tempMap.put("nonce_str", nonceStr);

        // 签名
        Map<String, String> params = SignUtils.paraFilter(tempMap);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        sign = MD5.sign(preStr, "&key=" + SwiftpassConfig.KEY, "utf-8");
        tempMap.put("sign", sign);

        // 将map转化为xml
        String xml = XmlUtils.toXml(tempMap);
        // 请求
        String result = HttpUtil.httpsRequest(SwiftpassConfig.REQ_URL, "POST", xml);
        try {
            Map<String, String> resultMap = XmlUtils.toMap(result);
            System.out.println(JSON.toJSONString(resultMap));
            if (!SignUtils.checkParam(resultMap, SwiftpassConfig.KEY)) {
                // 签名验证失败
                log.warn("签名验证失败");
            } else {
                if ("0".equals(resultMap.get("status")) && "0".equals(resultMap.get("result_code"))) {
                    //todo
                }
            }
        } catch (DocumentException e) {
            log.warn("威富通查询订单API xml to map", e);
        }
        return null;

    }

    /**
     * 查询退款订单API
     * https://open.swiftpass.cn/openapi/doc?index_1=3&index_2=1&chapter_1=191&chapter_2=216
     */
    public static Map<String, String> refundQuery(String outTradeNo) {

        // 接口类型
        String service = "unified.trade.refundquery";
        // 商户号
        String mchId = SwiftpassConfig.MCH_ID;
        // 随机字符串
        String nonceStr = getNonceStr();
        // 签名
        String sign;

        Map<String, String> tempMap = new HashMap<>(16);
        tempMap.put("service", service);
        tempMap.put("mch_id", mchId);
        tempMap.put("out_refund_no", outTradeNo);
        tempMap.put("nonce_str", nonceStr);

        // 签名
        Map<String, String> params = SignUtils.paraFilter(tempMap);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        sign = MD5.sign(preStr, "&key=" + SwiftpassConfig.KEY, "utf-8");
        tempMap.put("sign", sign);

        // 将map转化为xml
        String xml = XmlUtils.toXml(tempMap);
        // 请求
        String result = HttpUtil.httpsRequest(SwiftpassConfig.REQ_URL, "POST", xml);
        try {
            Map<String, String> resultMap = XmlUtils.toMap(result);
            System.out.println(JSON.toJSONString(resultMap));
            if (!SignUtils.checkParam(resultMap, SwiftpassConfig.KEY)) {
                // 签名验证失败
                log.warn("签名验证失败");
            } else {
                if ("0".equals(resultMap.get("status")) && "0".equals(resultMap.get("result_code"))) {
                    //todo
                }
            }
        } catch (DocumentException e) {
            log.warn("威富通查询订单API xml to map", e);
        }
        return null;

    }


    /**
     * 初始化请求API
     * https://open.swiftpass.cn/openapi/doc?index_1=3&index_2=1&chapter_1=191&chapter_2=212
     *
     * @param outTradeNo  商户订单号
     * @param body        商品描述
     * @param subOpenid   用户openid 测试账号不需要传
     * @param subAppid    公众账号或小程序ID
     * @param attach      附加信息
     * @param totalFee    总金额 分
     * @param mchCreateIp 终端IP
     * @return
     */
    public static Map<String, String> prepayment(String outTradeNo, String body, String subOpenid,
                                                 String attach, String totalFee, String mchCreateIp) {

        // 接口类型
        String service = "pay.weixin.jspay";
        // 商户号
        String mchId = SwiftpassConfig.MCH_ID;
        // 微信appid
        String subAppid = RedDotKey.APP_ID;
        // 原生JS 值为1
        String isRaw = "1";
        // 通知地址
        String notifyUrl = SwiftpassConfig.NOTIFY_URL;
        // 随机字符串
        String nonceStr = getNonceStr();
        // 总金额
        totalFee = getMoney(totalFee);
        // 签名
        String sign;

        Map<String, String> tempMap = new HashMap<>(16);
        tempMap.put("service", service);
        tempMap.put("mch_id", mchId);
        tempMap.put("is_raw", isRaw);
        tempMap.put("out_trade_no", outTradeNo);
        tempMap.put("body", body);
        tempMap.put("sub_openid", subOpenid);
        tempMap.put("sub_appid", subAppid);
        tempMap.put("attach", attach);
        tempMap.put("total_fee", totalFee);
        tempMap.put("mch_create_ip", mchCreateIp);
        tempMap.put("notify_url", notifyUrl);
        tempMap.put("nonce_str", nonceStr);

        // 签名
        Map<String, String> params = SignUtils.paraFilter(tempMap);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        sign = MD5.sign(preStr, "&key=" + SwiftpassConfig.KEY, "utf-8");
        tempMap.put("sign", sign);

        // 将map转化为xml
        String xml = XmlUtils.toXml(tempMap);
        // 请求
        String result = HttpUtil.httpsRequest(SwiftpassConfig.REQ_URL, "POST", xml);

        try {
            Map<String, String> resultMap = XmlUtils.toMap(result);
            if (!SignUtils.checkParam(resultMap, SwiftpassConfig.KEY)) {
                // 签名验证失败
                log.warn("签名验证失败");
            } else {
                if ("0".equals(resultMap.get("status")) && "0".equals(resultMap.get("result_code"))) {
                    String payInfo = resultMap.get("pay_info");
                    return (Map) JSON.parse(payInfo);
                }
            }
        } catch (DocumentException e) {
            log.warn("威富通初始化请求API 获取pay_info异常", e);
        }
        return null;
    }

    /**
     *
     * 退款API
     * https://open.swiftpass.cn/openapi/doc?index_1=3&index_2=1&chapter_1=191&chapter_2=217
     * @param outTradeNo 商户订单号
     * @param outRefundNo 商户退款单号
     * @param totalFee 总金额
     * @param refundFee 退款金额
     * @return
     */
    public static Map<String, String> refund(String outTradeNo, String outRefundNo, String totalFee, String refundFee) {

        // 接口类型
        String service = "unified.trade.refund";
        // 商户号
        String mchId = SwiftpassConfig.MCH_ID;
        // 操作员 操作员帐号,默认为商户号
        String opUserId = SwiftpassConfig.MCH_ID;
        // 随机字符串
        String nonceStr = getNonceStr();
        // 总金额
        totalFee = getMoney(totalFee);
        // 退款金额
        refundFee = getMoney(refundFee);
        // 签名
        String sign;

        Map<String, String> tempMap = new HashMap<>(16);
        tempMap.put("service", service);
        tempMap.put("mch_id", mchId);
        tempMap.put("out_trade_no", outTradeNo);
        tempMap.put("out_refund_no", outRefundNo);
        tempMap.put("total_fee", totalFee);
        tempMap.put("refund_fee", refundFee);
        tempMap.put("op_user_id", opUserId);
        tempMap.put("nonce_str", nonceStr);

        // 签名
        Map<String, String> params = SignUtils.paraFilter(tempMap);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        sign = MD5.sign(preStr, "&key=" + SwiftpassConfig.KEY, "utf-8");
        tempMap.put("sign", sign);

        // 将map转化为xml
        String xml = XmlUtils.toXml(tempMap);
        // 请求
        String result = HttpUtil.httpsRequest(SwiftpassConfig.REQ_URL, "POST", xml);

        try {
            Map<String, String> resultMap = XmlUtils.toMap(result);
            if (!SignUtils.checkParam(resultMap, SwiftpassConfig.KEY)) {
                // 签名验证失败
                log.warn("签名验证失败");
            } else {
                return resultMap;
            }
        } catch (DocumentException e) {
            log.warn("xml转map失败", e);
        }
        return null;
    }

    /**
     * 生成随机字符串 (采用14位当前日期数 + 4位随机整数)
     *
     * @return
     */
    public static String getNonceStr() {
        //获得当前日期
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String currTime = simpleDateFormat.format(new Date());
        return currTime + RandomUtil.fourDigit();
    }

    /**
     * 元转换成分
     *
     * @param amount
     * @return
     */
    public static String getMoney(String amount) {
        if (amount == null) {
            return "";
        }
        // 金额转化为分为单位 处理包含, ￥ 或者$的金额
        String currency = amount.replaceAll("\\$|\\￥|\\,", "");
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong = 0L;
        if (index == -1) {
            amLong = Long.valueOf(currency + "00");
        } else if (length - index >= 3) {
            amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
        } else if (length - index == 2) {
            amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
        } else {
            amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
        }
        return amLong.toString();
    }

    public static void main(String[] args) {

        Map<String,String> map = refundQuery("NO201904292256089303");
    }

}
